#include "dicomDict.h"
#include "xmlTagLoader.h"

using namespace dicom_dict;

///////////////////////////////////////////////////////////////////////////
// TXmlTagHandler /////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//
class TXmlTagHandler : public QXmlDefaultHandler 
{ 
public: 
	enum EMode{ LoadAll, LoadOne };
	//
	TXmlTagHandler( QMap <uint, TDicomElement> *tagMp
				  , QMap <QString, EType> *typeMp );
	//
	bool startElement(	const QString &namespaceURI, 
						const QString &localName, 
						const QString &qName, 
						const QXmlAttributes &attribs);
	bool endElement( const QString & namespaceURI
				   , const QString & localName
				   , const QString & qName );
	virtual bool characters( const QString &ch);
	//
	void setMode( TXmlTagHandler::EMode m, uint t = 0 ){ mode = m; tag = t; };

private:
	QMap<uint,TDicomElement> *tagMap;
	QMap <QString, EType> *typeMap;
	//
	uint tag;
	EMode mode;
	bool loadThis;
	TDicomElement elem;
};

///////////////////////////////
//
TXmlTagHandler::TXmlTagHandler( QMap <uint, TDicomElement>	*tagMp
							  , QMap <QString, EType> *typeMp )
: tagMap(tagMp)
, typeMap(typeMp)
, mode(LoadAll)
{}

//
bool TXmlTagHandler::startElement(	const QString &, const QString &, 
									const QString &qName, 
									const QXmlAttributes &attribs) 
{
	if( qName != "element" ) return true;
	loadThis = false;

	uint xmlTag = attribs.value("tag").toUInt(NULL, 16);
	if( mode == LoadAll  || xmlTag == tag ){
		tag = xmlTag;
		QString type = attribs.value("vr");
		if( type.contains('|') )
			elem.type = typeMap->value(type.left(2).toUpper() );
		else
			elem.type = typeMap->value( type );
		loadThis = true;
	}
	return true; 
}

//
bool TXmlTagHandler::characters(const QString &ch)
{
	if( loadThis )
		elem.description = ch;
	return true;
}

//
bool TXmlTagHandler::endElement(const QString &namespaceURI
							   , const QString &localName
							   , const QString &qName)
{
	if( loadThis ){
		tagMap->insert(tag, elem);
		if( mode == LoadOne ) return false;
	}
	return true;
}

///////////////////////////////////////////////////////////////////////////
// TXmlTagLoader //////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//
TXmlTagLoader::TXmlTagLoader( QMap <uint, TDicomElement>	*tagMp
							, QMap <QString, EType> *typeMp )
: tagMap(tagMp)
, typeMap(typeMp)
{
	reader  = new QXmlSimpleReader;
	handler = new TXmlTagHandler( tagMp, typeMp );
	reader->setContentHandler( handler );
}

//
bool TXmlTagLoader::loadAll( QFile &file )
{
	if( file.isOpen() ) file.reset();
	else				file.open(QIODevice::ReadOnly);

	handler->setMode( TXmlTagHandler::LoadAll );
	reader->parse( &file );
	return true;
}

//
bool TXmlTagLoader::loadOne( QFile &file, uint t )
{	
	if( file.isOpen() ) file.reset();
	else				file.open(QIODevice::ReadOnly);

	handler->setMode( TXmlTagHandler::LoadOne, t );
	reader->parse( &file );
	return true;
}

/**
QString escapeXml(const QString &str)
{ 
  QString xml = str; 
  xml.replace("&", "&amp;"); 
  xml.replace("<", "&lt;"); 
  xml.replace(">", "&gt;"); 
  xml.replace(" ", "&apos;"); 
  xml.replace("\"", "&quot;"); 
  return xml; 
}
/**/

//
void TXmlTagLoader::saveDict( QFile &file )
{
	QTextStream out( &file ); 

	out	<< "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; 
	out	<< "<dictionary>\n"; 
	
	QMap<uint,TDicomElement>::const_iterator it = tagMap->constBegin();
	while (it != tagMap->constEnd() ){
		QString tag("%1");
		tag = tag.arg( it.key(), 8, 16, QChar('0') );
		out << "  <element tag=\"" + tag + "\"" + " vr=\"" + typeMap->key(it.value().type) + "\">";
		out << it.value().description << "</element>\n";
		++it;
	}
	out	<< "</dictionary>\n"; 
}